#include "MessageProducer.h"
#include <spdlog/spdlog.h>
#include <chrono>

using TraderEngine::RedisConnection;
using TraderEngine::RedisPool;

namespace MessageFramework {

MessageProducer::MessageProducer(RedisPool* redisPool, const Config& config)
    : m_redisPool(redisPool), m_config(config) {

    if (!m_redisPool) {
        throw std::invalid_argument("RedisPool cannot be null");
    }

    if (m_config.publisherId.empty()) {
        throw std::invalid_argument("publisherId cannot be empty");
    }

    spdlog::info("MessageProducer created for publisher: {}", m_config.publisherId);
}

MessageProducer::MessageProducer(RedisPool* redisPool, const std::string& publisherId)
    : m_redisPool(redisPool) {

    if (!m_redisPool) {
        throw std::invalid_argument("RedisPool cannot be null");
    }

    m_config.publisherId = publisherId;
    spdlog::info("MessageProducer created for publisher: {}", m_config.publisherId);
}

void MessageProducer::fillAutoFields(MessageHeader& header) {
    // 1. 生成messageId
    if (std::strlen(header.messageId) == 0) {
        std::string msgId = MessageHeader::generateMessageId();
        std::strncpy(header.messageId, msgId.c_str(), sizeof(header.messageId) - 1);
    }

    // 2. 填充publisherId
    std::strncpy(header.publisherId, m_config.publisherId.c_str(),
                 sizeof(header.publisherId) - 1);

    // 3. 填充timestamp
    auto now = std::chrono::high_resolution_clock::now();
    header.timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
        now.time_since_epoch()).count();

    // 4. 填充traceId（如果设置了追踪上下文）
    if (!m_currentTraceId.empty() && std::strlen(header.traceId) == 0) {
        std::strncpy(header.traceId, m_currentTraceId.c_str(),
                     sizeof(header.traceId) - 1);
    }

    // 5. 填充parentId
    if (!m_currentParentId.empty() && std::strlen(header.parentId) == 0) {
        std::strncpy(header.parentId, m_currentParentId.c_str(),
                     sizeof(header.parentId) - 1);
    }

    // 6. 如果没有traceId，生成新的
    if (std::strlen(header.traceId) == 0) {
        std::string traceId = MessageHeader::generateTraceId();
        std::strncpy(header.traceId, traceId.c_str(), sizeof(header.traceId) - 1);
    }

    // 7. 填充version
    if (std::strlen(header.version) == 0) {
        std::strncpy(header.version, "1.0", sizeof(header.version) - 1);
        header.version[sizeof(header.version) - 1] = '\0';
    }

    // 8. 填充contentType
    if (std::strlen(header.contentType) == 0) {
        std::strncpy(header.contentType, "JSON", sizeof(header.contentType) - 1);
        header.contentType[sizeof(header.contentType) - 1] = '\0';
    }
}

void MessageProducer::signMessage(MessageHeader& header, const std::string& body) {
    if (m_config.secretKey.empty()) {
        spdlog::warn("Secret key not configured, skipping signature");
        return;
    }

    SignatureHelper::sign(header, body, m_config.secretKey);
}

std::string MessageProducer::encryptBody(const std::string& body) {
    if (m_config.encryptionKey.empty()) {
        spdlog::error("Encryption key not configured");
        return "";
    }

    return EncryptionHelper::encrypt(body, m_config.encryptionKey);
}

std::string MessageProducer::sendToRedis(const MessageHeader& header, const std::string& body) {
    auto conn = m_redisPool->getConnection();
    if (!conn) {
        spdlog::error("Failed to get Redis connection");
        return "";
    }

    try {
        // 将Header转换为Redis字段
        auto fieldsMap = header.toRedisFields();

        // 转换为unordered_map
        std::unordered_map<std::string, std::string> fields(fieldsMap.begin(), fieldsMap.end());

        // 添加body字段
        fields["body"] = body;

        // XADD命令发送消息 (id="*"表示自动生成)
        std::string streamId = conn->xadd(header.targetStream, "*", fields, m_config.maxStreamLength);

        if (streamId.empty()) {
            spdlog::error("Failed to send message to stream: {}", header.targetStream);
        } else {
            spdlog::debug("Message sent to stream {} with ID: {}, messageId: {}",
                         header.targetStream, streamId, header.messageId);
        }

        m_redisPool->returnConnection(conn);
        return streamId;

    } catch (const std::exception& e) {
        spdlog::error("Exception while sending message: {}", e.what());
        m_redisPool->returnConnection(conn);
        return "";
    }
}

std::string MessageProducer::send(MessageHeader& header, const std::string& body) {
    // 1. 填充自动字段
    fillAutoFields(header);

    // 2. 准备消息体
    std::string finalBody = body;

    // 3. 加密消息体（如果需要）
    if (m_config.autoEncrypt) {
        finalBody = encryptBody(body);
        if (finalBody.empty()) {
            spdlog::error("Failed to encrypt message body");
            return "";
        }
        header.encrypted = true;
        std::strncpy(header.encryptionAlgo, "AES-256-GCM", sizeof(header.encryptionAlgo) - 1);
        header.encryptionAlgo[sizeof(header.encryptionAlgo) - 1] = '\0';
    }

    // 4. 设置contentLength
    header.contentLength = static_cast<int>(finalBody.size());

    // 5. 签名消息（如果需要）
    if (m_config.autoSign) {
        signMessage(header, finalBody);
    }

    // 6. 验证消息头
    if (!header.validate()) {
        spdlog::error("Message header validation failed");
        return "";
    }

    // 7. 发送到Redis Stream
    return sendToRedis(header, finalBody);
}

std::string MessageProducer::send(const std::string& targetStream,
                                  const std::string& messageType,
                                  const std::string& body,
                                  const std::string& consumerId) {
    MessageHeader header;

    // 填充基本字段
    std::strncpy(header.targetStream, targetStream.c_str(), sizeof(header.targetStream) - 1);
    std::strncpy(header.messageType, messageType.c_str(), sizeof(header.messageType) - 1);

    if (!consumerId.empty()) {
        std::strncpy(header.consumerId, consumerId.c_str(), sizeof(header.consumerId) - 1);
    }

    return send(header, body);
}

std::string MessageProducer::sendRequest(const std::string& targetStream,
                                         const std::string& messageType,
                                         const std::string& body,
                                         const std::string& replyStream,
                                         const std::string& consumerId) {
    MessageHeader header;

    // 填充基本字段
    std::strncpy(header.targetStream, targetStream.c_str(), sizeof(header.targetStream) - 1);
    std::strncpy(header.messageType, messageType.c_str(), sizeof(header.messageType) - 1);
    std::strncpy(header.replyStream, replyStream.c_str(), sizeof(header.replyStream) - 1);

    if (!consumerId.empty()) {
        std::strncpy(header.consumerId, consumerId.c_str(), sizeof(header.consumerId) - 1);
    }

    return send(header, body);
}

void MessageProducer::setTraceContext(const std::string& traceId, const std::string& parentId) {
    m_currentTraceId = traceId;
    m_currentParentId = parentId;
}

void MessageProducer::updateConfig(const Config& config) {
    m_config = config;
    spdlog::info("MessageProducer config updated for publisher: {}", m_config.publisherId);
}

} // namespace MessageFramework
